﻿// ------------------------------------------------------------------------
// 版权信息
// 版权归重庆虫儿飞科技有限公司所有。
// 所有权利保留。
// 官方网站：https://netokit.com
// 许可证信息
// Neto.Kit 项目主要遵循 MIT 许可证和 Apache 许可证（版本 2.0）进行分发和使用。
// 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。
// 
// 使用条款
// 使用本代码应遵守相关法律法规和许可证的要求。
// 
// 免责声明
// 对于因使用本代码而产生的任何直接、间接、偶然、特殊或后果性损害，我们不承担任何责任。
// 
// 其他重要信息
// Neto.Kit 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。
// 有关 Neto.Kit 项目的其他详细信息，请参阅位于源代码树根目录中的 COPYRIGHT 和 DISCLAIMER 文件。
// 
// 更多信息
// 请访问 https://netokit.com 获取更多关于 Neto.Kit 项目的许可证和版权信息。
// ------------------------------------------------------------------------

#region

using SkiaSharp;

#endregion

namespace Neto.Image;

/// <summary>
///     SkiaSharp 扩展
/// </summary>
public class SkiaSharpHelper
{
    /// <summary>
    ///     SkiaSharp压缩图片
    /// </summary>
    /// <example>
    ///     string source = "D:\\Images\\source.png";
    ///     //实验1 不改变尺寸，图片质量改为80，存为jpg图片
    ///     ImageTools.Compress(source, "D:\\Images\\target-1.jpg", 1920, 80);
    ///     //实验2 不改变尺寸，图片质量改为80，存为png图片
    ///     ImageTools.Compress(source, "D:\\Images\\target-2.png", 1920, 80);
    ///     //实验3 尺寸缩放到宽度800，图片质量改为80，存为jpg图片
    ///     ImageTools.Compress(source, "D:\\Images\\target-3.jpg", 800, 80);
    ///     //实验4 尺寸缩放到宽度800，图片质量改为60，存为jpg图片
    ///     ImageTools.Compress(source, "D:\\Images\\target-4.jpg", 800, 60);
    /// </example>
    /// <param name="filePath">原文件位置</param>
    /// <param name="newFilePath">生成目标文件位置</param>
    /// <param name="maxWidth">最大宽度，根据此宽度计算是否需要缩放，计算新高度</param>
    /// <param name="quality">图片质量，范围0-100</param>
    public static bool Compress(string filePath, string newFilePath, decimal maxWidth = 0, int quality = 100)
    {
        try
        {
            using (var file = File.OpenRead(filePath))
            using (var fileStream = new SKManagedStream(file))
            using (var bitmap = SKBitmap.Decode(fileStream))
            {
                var width = (decimal)bitmap.Width;
                var height = (decimal)bitmap.Height;
                var newWidth = width;
                var newHeight = height;
                //maxWidth 要大于0才进行缩放，否则不做处理
                if (maxWidth > 0 && width > maxWidth)
                {
                    newWidth = maxWidth;
                    newHeight = height / width * maxWidth;
                }

                using (var resized =
                       bitmap.Resize(new SKImageInfo((int)newWidth, (int)newHeight), SKFilterQuality.Medium))
                    if (resized != null)
                        using (var image = SKImage.FromBitmap(resized))
                        using (var writeStream = File.OpenWrite(newFilePath))
                        {
                            image.Encode(SKEncodedImageFormat.Jpeg, quality).SaveTo(writeStream);

                            return true;
                        }
            }
        }
        catch (Exception ex)
        {
            return false;
        }

        return false;
    }

    /// <summary>
    ///     压缩并裁切图片去除上下水印
    /// </summary>
    /// <param name="filePath">原文件位置</param>
    /// <param name="newFilePath">生成目标文件位置</param>
    /// <param name="maxWidth">最大宽度，根据此宽度计算是否需要缩放，计算新高度</param>
    /// <param name="top">顶部裁切高度，单位px</param>
    /// <param name="bottom">底部裁切高度，单位px</param>
    /// <param name="quality">图片质量，范围0-100</param>
    public static void CompressAndCut(string filePath, string newFilePath, decimal maxWidth = 0, int top = 0,
        int bottom = 0, int quality = 100)
    {
        using (var file = File.OpenRead(filePath))
        using (var fileStream = new SKManagedStream(file))
        using (var bitmap = SKBitmap.Decode(fileStream))
        {
            var width = (decimal)bitmap.Width;
            var height = (decimal)bitmap.Height;
            var newWidth = width;
            var newHeight = height;
            //maxWidth 要大于0才进行缩放，否则不做处理
            if (maxWidth > 0 && width > maxWidth)
            {
                newWidth = maxWidth;
                newHeight = height / width * maxWidth;
            }

            using (var resized = bitmap.Resize(new SKImageInfo((int)newWidth, (int)newHeight), SKFilterQuality.Medium))
                if (resized != null)
                    using (var surface =
                           SKSurface.Create(new SKImageInfo((int)newWidth, (int)newHeight - top - bottom)))
                    {
                        var canvas = surface.Canvas;
                        canvas.DrawBitmap(resized, 0, 0 - top);
                        using (var image = surface.Snapshot())
                        using (var writeStream = File.OpenWrite(newFilePath))
                            image.Encode(SKEncodedImageFormat.Jpeg, quality).SaveTo(writeStream);
                    }
        }
    }

    /// <summary>
    ///     SkiaSharp验证文件是否是图片
    /// </summary>
    /// <param name="filePath">文件完整路径</param>
    /// <returns></returns>
    public static bool IsImage(string filePath)
    {
        //验证是否图片
        try
        {
            //using var file = File.OpenRead(filePath);
            //using var fileStream = new SKManagedStream(file);
            using var bitmap = SKBitmap.Decode(filePath);
            //bitmap 不为空标识加载图片成功，是真图片
            return bitmap != null;
        }
        catch (Exception e)
        {
            return false;
        }
    }

    /// <summary>
    ///     SkiaSharp验证文件是否是图片
    /// </summary>
    /// <param name="file">上传的文件对象</param>
    /// <returns></returns>
    public static bool IsImage(IFormFile file)
    {
        //验证是否图片
        try
        {
            var dir = AppX.GetUploadDefaultFloder() + "\\" + "upload\\temp";
            var filePath =
                $"{dir}\\{DateTimeOffset.Now:yyyyMMddHHmmssfffff}{RandomHelper.GetInt(10000, 99999)}{file.FileName.GetExtension()}";
            FileHelper.CreateDirectory(dir);

            using (var fs = File.Create(filePath))
            {
                file.CopyTo(fs);
                fs.Flush();
            }

            //进行压缩
            var newFilePath = filePath.Replace(file.FileName.GetExtension(), "") +
                              $"_test{file.FileName.GetExtension()}";
            var isCompress = Compress(filePath, newFilePath, 10, 10);

            //压缩成功了，说明是图片

            //删除临时文件
            FileHelper.TryDeleteFile(filePath);
            FileHelper.TryDeleteFile(newFilePath);

            //bitmap 不为空标识加载图片成功，是真图片
            return isCompress;
        }
        catch (Exception e)
        {
            return false;
        }
    }
}